package com.atguigu.gmall.activity.receiver;

import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.service.SeckillGoodsService;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.model.activity.UserRecode;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;

@Component
public class SeckillReceiver {

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private SeckillGoodsService seckillGoodsService;

    @Autowired
    private RedisTemplate redisTemplate;

    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_TASK_1,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_TASK),
            key = {MqConst.ROUTING_TASK_1}
    ))
    public void importToRedis(Message message, Channel channel){
        try {
            //  先查询到数据库中当天要秒杀的商品.
            //  状态 “1” 剩余库存数>0 当天 = new Date(); 2022-04-02
            //  select date_format(start_time,'%Y-%m-%d')  from seckill_goods;
            QueryWrapper<SeckillGoods> seckillGoodsQueryWrapper = new QueryWrapper<>();
            seckillGoodsQueryWrapper.eq("status",1);
            seckillGoodsQueryWrapper.gt("stock_count",0);
            //  2022-04-02
            seckillGoodsQueryWrapper.eq("date_format(start_time,'%Y-%m-%d')", DateUtil.formatDate(new Date()));
            List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectList(seckillGoodsQueryWrapper);
            //  将集合数据放入缓存.
            if (!CollectionUtils.isEmpty(seckillGoodsList)){
                for (SeckillGoods seckillGoods : seckillGoodsList) {
                    //  分析使用的数据类型. hash hset key field value;
                    String seckillKey = RedisConst.SECKILL_GOODS;
                    //  判断缓存中是否已经有了秒杀商品，如果有了，则不添加数据，没有，则进行添加数据.
                    Boolean result = this.redisTemplate.opsForHash().hasKey(seckillKey, seckillGoods.getSkuId().toString());
                    if (result){
                        //  result = true; 表示当前秒杀商品在缓存中已经存在。
                        continue;
                    }
                    //  存储数据.
                    this.redisTemplate.opsForHash().put(seckillKey,seckillGoods.getSkuId().toString(),seckillGoods);
                    //  剩余库存数放入redis 中. list 数据类型来存储。
                    for (Integer i = 0; i < seckillGoods.getStockCount(); i++) {
                        //  key = seckill:stock:skuId  value = skuId;
                        this.redisTemplate.opsForList().leftPush(RedisConst.SECKILL_STOCK_PREFIX+seckillGoods.getSkuId(),seckillGoods.getSkuId().toString());
                    }
                    //  初始化商品的状态位！ skuId:1  publish seckillpush skuId:1
                    this.redisTemplate.convertAndSend("seckillpush",seckillGoods.getSkuId()+":1");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        //  手动确认：
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    //  监听秒杀下单：
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_SECKILL_USER,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_SECKILL_USER),
            key = {MqConst.ROUTING_SECKILL_USER}
    ))
    public void seckillOrder(UserRecode userRecode ,Message message,Channel channel){
        //  编写预下单业务。
        try {
            if (userRecode!=null){
                seckillGoodsService.seckillOrder(userRecode.getUserId(),userRecode.getSkuId());
                //seckillGoodsService.seckillOrder(userRecode);
            }
        } catch (Exception e) {
            //  如果有异常就记录信息。
            e.printStackTrace();
        }
        //  手动确认
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    //  监听秒杀减库存消息.
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_SECKILL_STOCK,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_SECKILL_STOCK),
            key = {MqConst.ROUTING_SECKILL_STOCK}
    ))
    public void seckillStock(Long skuId,Message message, Channel channel){
        try {
            //  判断
            if (skuId!=null){
                //  减库存..
                seckillGoodsService.seckillStock(skuId);
                //  updateSeckillStock(skuId)
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        //  消息确认。
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);

    }

    //  秒杀结束清空数据.
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_TASK_18,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_TASK),
            key = {MqConst.ROUTING_TASK_18}
    ))
    public void clearRedisData(Message message,Channel channel){
        try {
            //  清空数据操作 秒杀结束： 哪些商品属于秒杀结束。
            //  结束时间 end_time   status = 1;
            QueryWrapper<SeckillGoods> seckillGoodsQueryWrapper = new QueryWrapper<>();
            seckillGoodsQueryWrapper.eq("status",1);
            seckillGoodsQueryWrapper.le("end_time",new Date());
            //  秒杀结束的集合列表
            List<SeckillGoods> seckillGoodsList = this.seckillGoodsMapper.selectList(seckillGoodsQueryWrapper);
            //  删除数据：
            if (!CollectionUtils.isEmpty(seckillGoodsList)){
                for (SeckillGoods seckillGoods : seckillGoodsList) {
                    //  删除剩余的skuId 对应的库存数。
                    this.redisTemplate.delete(RedisConst.SECKILL_STOCK_PREFIX+seckillGoods.getSkuId());
                }
            }

            //  删除其他数据：
            this.redisTemplate.delete(RedisConst.SECKILL_GOODS);
            //  删除预下单数据.  用户只有到了提交订单的时候，系统才会删除数据。
            this.redisTemplate.delete(RedisConst.SECKILL_ORDERS);
            //  删除真正下单的数据
            this.redisTemplate.delete(RedisConst.SECKILL_ORDERS_USERS);

            //  修改数据库中的秒杀商品状态. 秒杀结束了，将商品的秒杀状态改为2 就可以了.
            SeckillGoods seckillGoods = new SeckillGoods();
            seckillGoods.setStatus("2");
            this.seckillGoodsMapper.update(seckillGoods,seckillGoodsQueryWrapper);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //  手动确认
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);

    }

}
